﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Xml.Serialization;

namespace InnovTech.Util.Crypto
{
    /// <summary>
    /// Represents a serializable Crtypto Algorithm.
    /// </summary>
    [Serializable]
    public sealed class SerializableCryptoAlgo
    {
        [NonSerialized]
        private Type _algoType;

        /// <summary>
        /// Gets the assembly name of the Crypto algorithm
        /// </summary>
        public string AssemblyName { get; set; }
        /// <summary>
        /// Gets the name of the Crypto algorithm
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// Gets the key of the Crypto algorithm
        /// </summary>
        public string Key { get; set; }
        /// <summary>
        /// Gets the iv of the Crypto algorithm
        /// </summary>
        public string IV { get; set; }

        

        private SerializableCryptoAlgo()
        {
        }

        public static SerializableCryptoAlgo Create(SymmetricAlgorithm algo)
        {
            return new SerializableCryptoAlgo
            {
                AssemblyName = algo.GetType().Assembly.GetName().FullName,
                Name = algo.GetType().FullName,
                Key = System.Convert.ToBase64String(algo.Key),
                IV = System.Convert.ToBase64String(algo.IV)
            };
        }

        public SymmetricAlgorithm Restore()
        {
            if (string.IsNullOrWhiteSpace(Name))
                throw new ArgumentNullException("The name of a CrytoAlgo can not be null or empty");
            if (string.IsNullOrWhiteSpace(Key))
                throw new ArgumentNullException("The key of a CrytoAlgo can not be null or empty");
            if (string.IsNullOrWhiteSpace(IV))
                throw new ArgumentNullException("The IV of a CrytoAlgo can not be null or empty");

            if (_algoType == null)
            {
                Assembly assembly = Assembly.Load(AssemblyName);
                _algoType = assembly.GetType(Name);
            }


            SymmetricAlgorithm algo = Activator.CreateInstance(_algoType) as SymmetricAlgorithm;
            algo.Key = System.Convert.FromBase64String(Key);
            algo.IV = System.Convert.FromBase64String(IV);

            return algo;
        }
    }
}
